# _*_ encoding: utf-8 _*_
# __author__ = 'lx'
from collections.abc import Iterable

from PIL import Image, ImageOps, ImageEnhance, __version__ as PILLOW_VERSION
from paddle import fluid
import sys
import collections
import random

import cv2
import numpy as np

if sys.version_info < (3, 3):
    Sequence = collections.Sequence
    Iterable = collections.Iterable
else:
    Sequence = collections.abc.Sequence
    Iterable = collections.abc.Iterable

__all__ = ['flip', 'resize']

try:
    import accimage
except ImportError:
    accimage = None
def flip(image, code):
    """
    Accordding to the code (the type of flip), flip the input image

    Args:
        image: Input image, with (H, W, C) shape
        code: Code that indicates the type of flip.
            -1 : Flip horizontally and vertically
            0 : Flip vertically
            1 : Flip horizontally

    Examples:
        .. code-block:: python

            import numpy as np
            from paddle.incubate.hapi.vision.transforms import functional as F

            fake_img = np.random.rand(224, 224, 3)

            # flip horizontally and vertically
            F.flip(fake_img, -1)

            # flip vertically
            F.flip(fake_img, 0)

            # flip horizontally
            F.flip(fake_img, 1)
    """
    return cv2.flip(image, flipCode=code)
def _is_pil_image(img):
    if accimage is not None:
        return isinstance(img, (Image.Image, accimage.Image))
    else:
        return isinstance(img, Image.Image)

def crop(img, top, left, height, width):
    """Crop the given PIL Image.

    Args:
        img (PIL Image): Image to be cropped. (0,0) denotes the top left corner of the image.
        top (int): Vertical component of the top left corner of the crop box.
        left (int): Horizontal component of the top left corner of the crop box.
        height (int): Height of the crop box.
        width (int): Width of the crop box.

    Returns:
        PIL Image: Cropped image.
    """
    if not _is_pil_image(img):
        raise TypeError('img should be PIL Image. Got {}'.format(type(img)))

    return img.crop((left, top, left + width, top + height))


def resize(img, size, interpolation=cv2.INTER_LINEAR):
    """
    resize the input data to given size

    Args:
        input: Input data, could be image or masks, with (H, W, C) shape
        size: Target size of input data, with (height, width) shape.
        interpolation: Interpolation method.

    Examples:
        .. code-block:: python

            import numpy as np
            from paddle.incubate.hapi.vision.transforms import functional as F

            fake_img = np.random.rand(256, 256, 3)

            F.resize(fake_img, 224)

            F.resize(fake_img, (200, 150))
    """

    if isinstance(interpolation, Sequence):
        interpolation = random.choice(interpolation)

    if isinstance(size, int):
        h, w = img.shape[:2]
        if (w <= h and w == size) or (h <= w and h == size):
            return img
        if w < h:
            ow = size
            oh = int(size * h / w)
            return cv2.resize(img, (ow, oh), interpolation=interpolation)
        else:
            oh = size
            ow = int(size * w / h)
            return cv2.resize(img, (ow, oh), interpolation=interpolation)
    else:
        return cv2.resize(img, size[::-1], interpolation=interpolation)

def resized_crop(img, top, left, height, width, size, interpolation=Image.BILINEAR):
    """Crop the given PIL Image and resize it to desired size.

    Notably used in :class:`~torchvision.transforms.RandomResizedCrop`.

    Args:
        img (PIL Image): Image to be cropped. (0,0) denotes the top left corner of the image.
        top (int): Vertical component of the top left corner of the crop box.
        left (int): Horizontal component of the top left corner of the crop box.
        height (int): Height of the crop box.
        width (int): Width of the crop box.
        size (sequence or int): Desired output size. Same semantics as ``resize``.
        interpolation (int, optional): Desired interpolation. Default is
            ``PIL.Image.BILINEAR``.
    Returns:
        PIL Image: Cropped image.
    """
    assert _is_pil_image(img), 'img should be PIL Image'
    img = crop(img, top, left, height, width)
    img = resize(img, size, interpolation)
    return img